import { test, expect, beforeEach } from 'vitest'

import { type MoveTimeTo, setupTimers, createMoveTimeTo } from '../../__testUtils__/timers'
import { createAnimator } from '../../__testUtils__/nodes'

setupTimers()

let moveTimeTo: MoveTimeTo

beforeEach(() => {
  moveTimeTo = createMoveTimeTo()
})

test('Should create parent and transition children', async () => {
  const parent = createAnimator(undefined, { manager: 'stagger' })
  const child1 = createAnimator(parent)
  const child2 = createAnimator(parent)
  const child3 = createAnimator(parent)
  queueMicrotask(() => child1.node.send('setup'))
  queueMicrotask(() => child2.node.send('setup'))
  queueMicrotask(() => child3.node.send('setup'))
  queueMicrotask(() => parent.node.send('setup'))

  expect(parent.node.state).toBe('exited')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.399)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.401)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.439)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.441)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.479)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.481)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.799)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.801)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.839)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.841)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.879)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.881)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')

  moveTimeTo(1)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
})

test('Should create parent with staggerReverse and transition children', async () => {
  const parent = createAnimator(undefined, { manager: 'staggerReverse' })
  const child1 = createAnimator(parent)
  const child2 = createAnimator(parent)
  const child3 = createAnimator(parent)
  queueMicrotask(() => child1.node.send('setup'))
  queueMicrotask(() => child2.node.send('setup'))
  queueMicrotask(() => child3.node.send('setup'))
  queueMicrotask(() => parent.node.send('setup'))

  expect(parent.node.state).toBe('exited')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.399)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.401)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.439)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.441)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.479)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.481)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.799)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.801)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entered')
  moveTimeTo(0.839)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entered')
  moveTimeTo(0.841)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  moveTimeTo(0.879)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  moveTimeTo(0.881)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')

  moveTimeTo(1)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
})

test('Should create combined parent and transition children', async () => {
  const parent = createAnimator(undefined, { combine: true, manager: 'stagger' })
  const child1 = createAnimator(parent)
  const child2 = createAnimator(parent)
  const child3 = createAnimator(parent)
  queueMicrotask(() => child1.node.send('setup'))
  queueMicrotask(() => child2.node.send('setup'))
  queueMicrotask(() => child3.node.send('setup'))
  queueMicrotask(() => parent.node.send('setup'))

  expect(parent.node.state).toBe('exited')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.001)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.039)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.041)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.079)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  moveTimeTo(0.081)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.399)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.401)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.439)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.441)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.479)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entering')
  moveTimeTo(0.481)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')

  moveTimeTo(1)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
})

test('Should create combined parent and transition children with custom durations', async () => {
  const parent = createAnimator(undefined, {
    active: false,
    combine: true,
    manager: 'stagger'
  })
  const child1 = createAnimator(parent, { duration: { enter: 0.2 } })
  const child2 = createAnimator(parent, { duration: { offset: 0.1 } })
  const child3 = createAnimator(parent, { duration: { enter: 0.1, delay: 0.05 } })
  const child4 = createAnimator(parent, { duration: { enter: 0.05 } })
  queueMicrotask(() => child4.node.send('setup'))
  queueMicrotask(() => child3.node.send('setup'))
  queueMicrotask(() => child2.node.send('setup'))
  queueMicrotask(() => child1.node.send('setup'))
  queueMicrotask(() => parent.node.send('setup'))

  expect(parent.node.state).toBe('exited')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1)
  expect(parent.node.state).toBe('exited')
  expect(child1.node.state).toBe('exited')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')

  parent.node.control.setSettings({ active: true })
  parent.node.send('update')

  moveTimeTo(1)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering') // Enters at the same time as the parent
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.039)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.041)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('exited') // Node duration offset
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.139)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.141)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering') // 1 + 0.04*1 + 0.1 = 1.140
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.179)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.181)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited') // Node duration delay
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.199)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.201)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered') // enter = 0.2
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.218)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  moveTimeTo(1.221)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('entering') // 1 + 0.04*3 + 0.1 = 1.220
  moveTimeTo(1.228)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('entering')
  moveTimeTo(1.231)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering') // 1 + 0.04*2 + 0.1 + 0.05 = 1.230
  expect(child4.node.state).toBe('entering')
  moveTimeTo(1.268)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('entering')
  moveTimeTo(1.271)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('entered') // enter = 0.05
  moveTimeTo(1.328)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('entered')
  moveTimeTo(1.331)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entered') // enter = 0.1
  expect(child4.node.state).toBe('entered')
  moveTimeTo(1.538)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  moveTimeTo(1.541)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered') // enter = 0.4
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')

  moveTimeTo(3)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
})

test('Should create combined parent and transition dynamically updated children', async () => {
  const parent = createAnimator(undefined, {
    combine: true,
    manager: 'stagger',
    duration: { stagger: 0.5 }
  })
  const child1 = createAnimator(parent, { duration: { enter: 1 } })
  const child2 = createAnimator(parent, { duration: { enter: 1 } })
  const child3 = createAnimator(parent, { duration: { enter: 1 } })
  const child4 = createAnimator(parent, { duration: { enter: 1 } })
  const child5 = createAnimator(parent, { duration: { enter: 1 } })
  queueMicrotask(() => child1.node.send('setup'))
  queueMicrotask(() => child2.node.send('setup'))
  queueMicrotask(() => child3.node.send('setup'))
  queueMicrotask(() => child4.node.send('setup'))
  queueMicrotask(() => child5.node.send('setup'))
  queueMicrotask(() => parent.node.send('setup'))

  moveTimeTo(0.001)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  expect(child5.node.state).toBe('exited')

  moveTimeTo(1.2)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('exited')
  expect(child5.node.state).toBe('exited')
  parent.system.unregister(child1.node) // Remove node already entered.
  parent.system.unregister(child5.node) // Remove node not entering yet.
  const child6 = createAnimator(parent, { duration: { enter: 1 } })
  const child7 = createAnimator(parent, { duration: { enter: 1 } })
  queueMicrotask(() => child6.node.send('setup'))
  queueMicrotask(() => child7.node.send('setup'))

  moveTimeTo(1.499)
  expect(parent.node.state).toBe('entering')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('exited')
  expect(child6.node.state).toBe('exited')
  expect(child7.node.state).toBe('exited')
  moveTimeTo(1.501)
  expect(parent.node.state).toBe('entering')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('entering')
  expect(child6.node.state).toBe('exited')
  expect(child7.node.state).toBe('exited')
  moveTimeTo(1.999)
  expect(parent.node.state).toBe('entering')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('entering')
  expect(child6.node.state).toBe('exited')
  expect(child7.node.state).toBe('exited')
  moveTimeTo(2.001)
  expect(parent.node.state).toBe('entering')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entering')
  expect(child6.node.state).toBe('entering')
  expect(child7.node.state).toBe('exited')
  moveTimeTo(2.499)
  expect(parent.node.state).toBe('entering')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entering')
  expect(child6.node.state).toBe('entering')
  expect(child7.node.state).toBe('exited')
  moveTimeTo(2.501)
  expect(parent.node.state).toBe('entering')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child6.node.state).toBe('entering')
  expect(child7.node.state).toBe('entering')
  moveTimeTo(2.999)
  expect(parent.node.state).toBe('entering')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child6.node.state).toBe('entering')
  expect(child7.node.state).toBe('entering')
  moveTimeTo(3.001)
  expect(parent.node.state).toBe('entered') // Parent node initial calculation only included 5 children.
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child6.node.state).toBe('entered')
  expect(child7.node.state).toBe('entering')
  moveTimeTo(3.499)
  expect(parent.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child6.node.state).toBe('entered')
  expect(child7.node.state).toBe('entering')
  moveTimeTo(3.501)
  expect(parent.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child6.node.state).toBe('entered')
  expect(child7.node.state).toBe('entered')

  moveTimeTo(4)
  expect(parent.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child6.node.state).toBe('entered')
  expect(child7.node.state).toBe('entered')
})

test('Should create combined parent and transition dynamically updated children with refresh event', () => {
  const parent = createAnimator(undefined, {
    combine: true,
    manager: 'stagger',
    duration: { stagger: 0.5 }
  })
  const child1 = createAnimator(parent, { duration: { enter: 1 } })
  const child2 = createAnimator(parent, { duration: { enter: 1 } })
  const child3 = createAnimator(parent, { duration: { enter: 1 } })
  const child4 = createAnimator(parent, { duration: { enter: 1 } })
  const child5 = createAnimator(parent, { duration: { enter: 1 }, condition: () => false })
  const child6 = createAnimator(parent, { duration: { enter: 1 } })
  queueMicrotask(() => child1.node.send('setup'))
  queueMicrotask(() => child2.node.send('setup'))
  queueMicrotask(() => child3.node.send('setup'))
  queueMicrotask(() => child4.node.send('setup'))
  queueMicrotask(() => child5.node.send('setup'))
  queueMicrotask(() => child6.node.send('setup'))
  queueMicrotask(() => parent.node.send('setup'))

  moveTimeTo(0.001)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entering')
  expect(child2.node.state).toBe('exited')
  expect(child3.node.state).toBe('exited')
  expect(child4.node.state).toBe('exited')
  expect(child5.node.state).toBe('exited')
  expect(child6.node.state).toBe('exited')

  moveTimeTo(1.2)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('exited')
  expect(child5.node.state).toBe('exited')
  expect(child6.node.state).toBe('exited')

  child5.node.control.setSettings({ condition: () => true })
  queueMicrotask(() => parent.node.send('refresh'))

  moveTimeTo(1.201)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('exited')
  expect(child5.node.state).toBe('exited')
  expect(child6.node.state).toBe('exited')
  moveTimeTo(1.499)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entering')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('exited')
  expect(child5.node.state).toBe('exited')
  expect(child6.node.state).toBe('exited')
  moveTimeTo(1.501)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('entering')
  expect(child5.node.state).toBe('exited')
  expect(child6.node.state).toBe('exited')
  moveTimeTo(1.999)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entering')
  expect(child4.node.state).toBe('entering')
  expect(child5.node.state).toBe('exited')
  expect(child6.node.state).toBe('exited')
  moveTimeTo(2.001)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entering')
  expect(child5.node.state).toBe('exited')
  expect(child6.node.state).toBe('entering')
  moveTimeTo(2.499)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entering')
  expect(child5.node.state).toBe('exited')
  expect(child6.node.state).toBe('entering')
  moveTimeTo(2.501)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child5.node.state).toBe('entering')
  expect(child6.node.state).toBe('entering')
  moveTimeTo(2.999)
  expect(parent.node.state).toBe('entering')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child5.node.state).toBe('entering')
  expect(child6.node.state).toBe('entering')
  moveTimeTo(3.001)
  expect(parent.node.state).toBe('entered') // Parent node initially only calculated 5 children.
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child5.node.state).toBe('entering')
  expect(child6.node.state).toBe('entered')
  moveTimeTo(3.499)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child5.node.state).toBe('entering')
  expect(child6.node.state).toBe('entered')
  moveTimeTo(3.501)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child5.node.state).toBe('entered')
  expect(child6.node.state).toBe('entered')

  moveTimeTo(7)
  expect(parent.node.state).toBe('entered')
  expect(child1.node.state).toBe('entered')
  expect(child2.node.state).toBe('entered')
  expect(child3.node.state).toBe('entered')
  expect(child4.node.state).toBe('entered')
  expect(child5.node.state).toBe('entered')
  expect(child6.node.state).toBe('entered')
})

test.todo('Should create combined parent and transition children with staggerLimit')
